﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

//전투 관련 공식들 모음//
public class BattleFormula : MonoBehaviour {
	
	//스킬 발동 확률//
	public static float GetSkillChance(DSkills skill , int critical)
	{
		float prob = 0;
		if(skill.rateType == 1)//고정확률
			prob = skill.rate;
		else if(skill.rateType == 2 || skill.rateType == 3)//일반확률,높은확률
		{
			prob = 1.0f/ ( 1 + Mathf.Pow(10, ( (300-critical*2)/200.0f) ) ) - 0.4f;
			if(skill.rateType == 2) {
				if(prob>0.5f)
					prob = 0.5f;
			}
			else {
				prob = prob * 2;
				if(prob>0.9f)
					prob = 0.9f;
			}
		}
		return prob;
	}

	//일반 공격 데미지 계산
	public static int CalcNormalDamage(UnitStat stat, BattlePawn target)
	{
		return CalcNormalDamage(stat, target.stat);
	}

	public static int CalcNormalDamage(UnitStat stat, UnitStat target)
	{
		return GetDamageMod(stat, GetDamageDecreaseRatio(stat, target));
	}
	
	static int GetDamageMod(UnitStat stat, float damPercent)
	{
		if (BattleCheat.Instance != null)
		{
			if (BattleCheat.Instance.damageCheatPlayer >= 0)
			{
				foreach (var player in BattleManager.Instance.playerList)
				{
					if (player.stat == stat)
						return BattleCheat.Instance.damageCheatPlayer;
				}
			}

			if (BattleCheat.Instance.damageCheatEnemy >= 0)
			{
				foreach (var enemy in BattleManager.Instance.enemyList)
				{
					if (enemy.stat == stat)
						return BattleCheat.Instance.damageCheatEnemy;
				}
			}
		}

		int damage = 0;
		if(IsMeleeAttack(stat.atkType))
			damage =  (int)(damPercent * stat.atk * Random.Range(0.9f, 1.0f) );
		else
			damage =  (int)(damPercent * stat.atk * Random.Range(0.7f, 1.0f) );
		return damage;
	}

	//데미지 감소율 계산( 상대방 방어도 , 저항치 반영)
	public static float GetDamageDecreaseRatio(UnitStat stat, UnitStat target)
	{
		int D = 6;
		float maxDamPercent = 0.35f;

		int def = target.def;
		if(!IsMeleeAttack(stat.atkType))
			def = target.resist;
		float damPercent = 1 - def/(float)(def + D*stat.level);
//		Debug.Log(stat.atkType+"  damPercent="+damPercent);
		if(damPercent>maxDamPercent)
			damPercent=maxDamPercent;
		return damPercent;
	}

	public static bool IsMeleeAttack(int atkType) 
	{
		if(atkType == 1)
			return true;
		return false; 
	}

	//원호 공격 데미지 보정//
	public static int GetSupportAtkDamageModified(int supportAttackCount, UnitStat stat, BattlePawn target)
	{
		int damage = CalcNormalDamage(stat, target);
		if(supportAttackCount==1)
			damage = (int)(damage * 1.05f);
		else if(supportAttackCount==2) 
			damage = (int)(damage * 1.1f);
		else 
			damage = (int)(damage * 1.2f);
		return damage;
	}

	//원호 방어 데미지 보정//
	public static int GetSupportDefDamageModified(UnitStat stat, BattlePawn target)
	{
		return GetDamageMod( stat, GetDamageDecreaseRatio(stat, target.stat) * 0.8f );
	}

	//원호 공격 확률//
	public static float GetSupportAtkProb(int supportAtk)
	{
		//return (supportAtk-50)/1000.0f + 0.14f;
		return (supportAtk-50)/1000.0f + 0.14f + 0.3f; // 시연용 30%증가//
	}

	//원호 방어 확률//
	public static float GetSupportDefProb(int supportDef)
	{
		return (supportDef-50)/1500.0f + 0.1f;
	}

	public static int GetRageDamageModified(UnitStat stat, BattlePawn target, int targetLength)
	{
		float damMod = 1.0f;
		if(targetLength==1)
			damMod = 1.5f;
		else if(targetLength==2)
			damMod = 1.25f;
		return (int)(stat.atk * GetDamageDecreaseRatio(stat, target.stat) * damMod );
	}

	public static int GetFriendDamageModified(UnitStat stat, BattlePawn target, int targetLength)
	{
		return GetRageDamageModified(stat, target, targetLength);
	}

	public static int GetSkillDamage(UnitStat stat, DSkills skill, BattlePawn target)
	{
		if (BattleCheat.Instance != null)
		{
			if (BattleCheat.Instance.damageCheatPlayer >= 0)
			{
				foreach (var player in BattleManager.Instance.playerList)
				{
					if (player.stat == stat)
						return BattleCheat.Instance.damageCheatPlayer;
				}
			}

			if (BattleCheat.Instance.damageCheatEnemy >= 0)
			{
				foreach (var enemy in BattleManager.Instance.enemyList)
				{
					if (enemy.stat == stat)
						return BattleCheat.Instance.damageCheatEnemy;
				}
			}
		}

		float baseDamage = GetDamageMod(stat, skill.skillMod)/(float)skill.targetNumber;
		return (int)(baseDamage * GetDamageDecreaseRatio(stat, target.stat));
	}

	//주목도에 의해 타겟정함
	public static BattlePawn GetTargetByTaunt(List<BattlePawn> pawnList)
	{
		if( 0 == pawnList.Count )
			return null;
		
		float AP = 1.15f; // 주목도 보정치
		float tauntTotal = 0;
		float [] tauntList = new float[pawnList.Count];
		int i=0;
		foreach(BattlePawn pawn in pawnList)
		{
			//Debug.Log(i+" pawnTaunt = "+pawn.stat.taunt);
			tauntList[i] = Mathf.Pow ( pawn.stat.taunt, AP);
			tauntTotal += tauntList[i];
			i++;
		}
		float probAcc = 0;
		for(i=0; i<tauntList.Length;i++) {
			tauntList[i] = tauntList[i]/tauntTotal + probAcc;
			probAcc += tauntList[i];
			//Debug.Log(i+" probAcc = "+probAcc);
		}
		int nIndex = 0;
		float prob = Well512.Instance.NextFloat();
		for(i=0; i<tauntList.Length;i++) {
			if(prob<=tauntList[i]) {
				nIndex = i;
				//Debug.Log(prob+" taunt selected  "+nIndex);
				break;
			}
		}
		
		return pawnList[nIndex];
	}

	public static float GetDeltaRage(int damage, int maxHp)
	{
		float deltaRage = 5 * (damage/(maxHp*0.2f) );
		if(deltaRage<5)
			deltaRage=5;
		return deltaRage;
	}

	//공격 순서 결정
	public static void CalcAttackOrder(List<BattlePawn> playerList, List<BattlePawn> enemyList)
	{
		float playerLev = 0;
		foreach(BattlePawn pawn in playerList) {
			playerLev += pawn.stat.level;
			pawn.InitAtkOrder();
		}
		playerLev = playerLev/playerList.Count;
		
		float enemyLev = 0;
		foreach(BattlePawn pawn in enemyList) {
			enemyLev += pawn.stat.level;
			pawn.InitAtkOrder();
		}
		enemyLev = enemyLev/enemyList.Count;
		
		float penalty = 1;
		bool isPlayerPenalty=false;
		if(playerLev < enemyLev) {
			penalty = playerLev/enemyLev;
			isPlayerPenalty=true;
		}
		else if(playerLev > enemyLev) {
			penalty = enemyLev/playerLev;
			isPlayerPenalty=false;
		}
		
		Debug.Log("average level player="+playerLev+"  enemy="+enemyLev+"  penalty="+penalty);
		
		//List<BattlePawn> pawnList = playerList.Union(enemyList).ToList();
		
		if(penalty<1)
		{
			if(isPlayerPenalty) {
				foreach(BattlePawn pawn in playerList) {
					pawn.atkOrder = (float)pawn.stat.prior * penalty;
				}
			}
			else {
				foreach(BattlePawn pawn in enemyList) {
					pawn.atkOrder = (float)pawn.stat.prior * penalty;
				}
			}
		}
		
	}
}
